package _1011.review;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Random;
import java.util.Scanner;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.junit.Test;
/*
 *	jvm java虚拟机三个子系统：
 *	ClassLoader: 类加载器(把class字节码中的类加载到内存)
 *  ExecuteEngine: 执行引擎 (执行器)
 *  运行时数据区(内存结构)
 */
public class Review {
	

	public Review() {
		super();
		System.out.println("constructor ...");
	}

	
	
	/*
	 *  1.java程序从main开始，从main结束
	 *  2.源文件.java后缀
	 *  3.javac 源文件.java  -> 生成  源文件.class字节码   jvm(java虚拟机)   complier(编译)
	 *  4.java  源文件    运行，让jvm干活
	 *  5.一个源文件可以声明几个类？无数个类，但是只能有一个public类（主类），主类和文件同名，main只能声明在主类中
	 */

	/*
	 *  1. byte(1) short(2) int(4) long(8) float(4) double(8) boolean(1) char(2)
	 *  2. boolean不能转换成其他7种类型, boolean 是true和false
	 *  3. byte,short,char -> int -> long -> float -> double  小类型给大类型转换向上转型
	 *  	大类型赋值小类型强制类型转换(小类型)
	 *  4. long的值超过int范围必须L, float必须在值后F
	 *  5. float包括整数精确7位，double包括整数15位
	 *  6. 标识符命名规范
	 *  	1. 可以有数字，字母，_, $
	 *  	2. 数字不能开头
	 *      3. 不能使用保留字goto和关键字
	 *      4. 见名知意
	 *  
	 *  阿里规范：
	 *  	类名： 大驼峰   TankWar
	 *  	包名:  全小写   java.util.function
	 *  	变量名和方法名： 小驼峰   getAge  myName
	 *  	常量名： 全大写  MAX_VALUE
	 */
	@Test
	public void basicType() {
		// -128 ~ 127 
		byte b = 100;
		// -32768 ~ 32767
		short s = 32767;
		// -21亿 ~21亿
		int i = 11010101;
		// 19位数字
		long l = 1231313213131121L;
		
		float f = 12345.678F;
		double d = 1231323.13133132;
		
		// unicode: 0~65535
		char c1 = '哈';
		char c2 = 97;  // 'a'=97   'A'=65   '0'=48
		char c3 = '\u0030';   // 16进制的48
		char c4 = '\n';    // \n 换行  \t制表符(4个空格)
		System.out.println(c3);
	}
	
	/*
	 * 1. 整数相除结果一定是整数
	 * 2. 底层逻辑一定转换成相同类型才可以运算, 参与运算的最小单位是int
	 *    byte,short,char看到 +,-,*,/,% 提升为int类型再运算
	 * 3. 取余运算符正负号和第一个运算数一致
	 * 4. 关系运算符 > ,>= ,< ,<= , ==, !=  结果是boolean
	 * 5. 逻辑运算符： &&  ||  !,    !优先级 > &&  > ||
	 * 		短路运算符: false && 后面不执行
	 * 				    true || 后面不执行
	 * 6. 三目运算符:  boolean ? true: false;
	 */
	@Test
	public void operator() {
		System.out.println(10/4);
		System.out.println(-10 % 4);
		
		int i = 1;
		System.out.println(++i);
		int j = 2;
		System.out.println(j--);
	}
	
	/*
	 *  1. switch(value) : byte,short,char,int,String,enum
	 */
	@Test
	public void statement() {
		int i = 1;
		
		if(true) {
		}
		
		if(i == 1) {
		}else {
		}
		
		if (i == 1) {	
		}else if (i == 2) {
		}else {
		}
		
		switch(i) {
			case 1:break;
			case 2:break;
			case 3:break;
			default: break;
		}
		
		while(i < 10) {
			i++;
		}
		
		do {
			i++;
		}while(i < 10);
		
		loop:
		for(int h = 0 ; h < 3 ; h++) {
			for(int j = 0 ; j < 3; j++) {
				if (j == 0) {
					continue; // 进入循环的下一轮
				}
				if (j == 2) {
					break;   // 结束所在内层循环
				}
				if (j ==1) {
					break loop;
				}
			}
		}
	}

	/*
	 * 1. 数组是一组相同类型数据的集合
	 * 2. 定义数组：  类型[] 引用名 = new 类型[空间];
	 * 3. 使用下标获取每个元素值，下标从0开始
	 * 4. 数组只要开辟空间了，都有默认值
	 * 		byte 0, short 0, int  0, long 0L, float 0.0F , double 0.0 , char '\0', boolean false
	 * 		Object null
	 */
	@Test
	public void array() {
		int[] a = {1,2,4};
		int[] a2 = new int[] {1,2,4};
		
		int[] a3 = new int[3];
		a3[0] = 1;
		a3[1] = 2;
		a3[2] = 3;
		
		// jdk5增强for循环
		for(int t : a3) {
			System.out.println(t);
		}
		
		// 冒泡排序
		for(int j = 0 ; j < a3.length -1; j++) {
			for(int i = 0 ; i < a3.length-1 ; i++) {
				if (a3[i] > a3[i+1]) {
					int t = a3[i];
					a3[i] = a3[i+1];
					a3[i+1] = t;
				}
			}
		}
		
		// 数组的拷贝方式:
		int[] copy = new int[5];
		System.arraycopy(a3, 0, copy, 0, a3.length);
		int[] copyOf = Arrays.copyOf(a3,10);
		int[] clone = a3.clone();
		
	}
	
	
	class Student{
		// 属性私有的
		private String name;
		private int age;
		/*
		 * 构造方法: 1.和类同名  2.没有返回值  3.创建对象同时自动调用 4.如果自己声明构造方法默认的空构造就不送了
		 * 功能： 初始化对象属性
		 */
		public Student() {
			super();
		}
		public Student(String name, int age) {
			super();
			this.name = name;
			this.age = age;
		}
		
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		// 访问修饰符  返回值类型void  方法名(参数列表) { 方法体; }
		public int getScore() {
			return 100;
		}
	}
	
	/*
	 *  4个访问修饰符   本类   本包    跨包子类      跨包非子类
	 *     public       V      V         V             V
	 *     protected    V      V         V 
	 *     默认没有      V      V  
	 *     private      V
	 */
	
	class ThisDemo extends Object{
		String name;
		ThisDemo(){
			super();
		}
		ThisDemo(String name){
			this();  // 3.调用本类其他构造方法，必须写在构造方法里的第一行
			this.name = name;
		}
		
		public void setName(String name) {
			//1.this区分属性和参数同名
			this.name = name;
		}
		
		public ThisDemo getObj() {
			// 2.返回调用当前方法的对象
			return this;
		}
	}
	
	class MyMath{
		// 方法重载： 功能相同，方法名相同，参数列表不同（个数不同，类型不同）
		public int add(int a,int b) {
			return a + b;
		}
		public int add(int a, int b ,int c) {
			return a + b + c;
		}
		public double add(int a, double b) {
			return a + b;
		}
		public double add(double a, double b) {
			return a + b;
		}
		// 可变长参数，一个方法中只能有一个， 放在最后一个参数上，底层处理成数组
		// 具体参数的优先于可变长参数的
		public int add(int...args) {
			int sum = 0;
			for(int i = 0 ; i< args.length ;i ++) {
				sum += args[i];
			}
			return sum;
		}
		
		// add(1,2,3,4,5,6);
	}
	
	@Test
	public void classObject() {
		// 1.创建对象
		Student s = new Student("zs",30);
		// 2.调用方法
		s.setAge(20);
		System.out.println(s.getAge());
		System.out.println(s.getName());
	}
	
	static class Cat{
		String type;
	}
	static class Dog{
		String name;
	}
	
	static class Person{
		// Person包含Cat
		Cat cat;
		// 静态是属于类的，必须使用类名.调用，独此一份，每个对象可以共享
		static String star;
		// 独此一份还不能改的
		static final String STAR_CODE = "x0101";
		
		// 人依赖狗
		public void walkDog(Dog dog) {
			System.out.println(dog.name);
		}
		
		public static void print(Person p) {
			// 静态方法中可以直接访问本类静态属性和方法
			// 非静态的属性和方法必须使用对象调用
			// 静态方法中不能使用this关键字
			p.cat = new Cat();
			System.out.println(star);
		}
	}
	
	@Test
	public void denpendency() {
		Dog d = new Dog();
		d.name = "abc";
		
		Person p = new Person();
		p.walkDog(d);
		
		Cat c = new Cat();
		c.type= "波斯猫";
		p.cat = c;
		
		Person.star = "earth";
		
		// 常量 
		final int LIFE = 3;
		
		System.out.println(Person.STAR_CODE);
		
		System.out.println((Long.MAX_VALUE+"").length());
		System.out.println(Long.MIN_VALUE);
	}
	
	@Test  // 位运算
	public void binary() throws InterruptedException {
		System.out.println(10 << 1);
		System.out.println(10 << 2);
		System.out.println(10 << 3);
		System.out.println(10 >> 1);
		System.out.println(10 >> 2);
		System.out.println(10 >> 3);
	}
	
	// 静态块
	static {
		System.out.println("static block 1");
	}
	static {
		System.out.println("static block 2");
	}
	// 非静态块
	{
		System.out.println("non static block");
	}
	{
		System.out.println("non static block2");
	}
	
	@Test   // 运行时机: 1.执行所有静态块  2.执行main方法  3.main创建对象，非静态块  4.对象的构造方法
	public void runtime() {
		Review r = new Review();
		Review r2 = new Review();
		Review r3 = new Review();
	}
	
	/*
	 *  final和finally和finalize的区别
	 *  1.final 修饰常量值不能改
	 *  2.final 修饰方法不能重写
	 *  3.final 修饰类不能被继承
	 *  
	 *  finally是try-catch-finally, 无论try中是否有异常，finally都会被执行
	 *  
	 *  finalize是Object类声明，堆中的对象被销毁前调用的方法
	 */
	class A{
		int a;
		private int b;
		public A(int a,int b) {
			super();  // Object()
			this.a = a;
			this.b = b;
		}
		public int getB() {
			return b;
		}
		public void setB(int b) {
			this.b = b;
		}
		public  void testA() throws IOException{
			System.out.println("test");
		}
	}
	// 单继承: 子类继承了父类所有属性和方法，除了构造、静态方法，但是子类可以通过super()调用父类构造方法
	class B extends A{
		int c;
		public B(int a,int b,int c) {
			// 父类如果没有无参构造，则子类构造需要显示调用父类的带参构造
			super(a,b); // 调用父类的构造目的初始化子类继承来的属性
			this.c = c;
		}
		public void test() {
			System.out.println(a);
			setB(2);
			System.out.println(getB());
		}
		/* 
		 *  方法重写：
		 *  1.方法头要一样
		 *  2.访问修饰符>=父类访问修饰符
		 *  3.不能比父类抛出更多的非运行时异常
		 *  
		 *  子类不能重写父类： 1.父类构造方法  2.静态方法 3.final方法
		 */
		@Override
		public void testA() throws IOException {
			// 子类自己的属性和方法，直接调用
			this.c = 3;   // this包括super的范围
			this.getB();
			
			// 继承的父类可以使用
			super.testA();
			super.a = 1;
			super.b = 2;
			System.out.println(super.b);
		}
		
	}
	
	@Test
	public void inherit() throws IOException {
		// 子类对象给父类引用，向上转型, a只能访问B继承到的部分
		A a = new B(1,2,3);
		// 父类给子类引用赋值，强制类型转换
		((B)a).c = 1;
		
		// 判断a引用指向的对象是否属于某类型
		System.out.println(a instanceof A);
		System.out.println(a instanceof B);
		
		a.testA();
	}
	
	/*
	 * 接口: 规范，能力，红头文件
	 * 1. 静态常量
	 * 2. 抽象方法
	 * 3. 静态方法
	 * 4. 默认方法
	 * 接口直接可以使用extends 多继承
	 * 类和接口是implements 多实现
	 */
	interface IA{}
	interface IB{}
	interface IC{}
	interface Lifeable extends IA,IB{
		
	}
	// 如果类中有抽象方法，则必须声明为抽象类
	abstract class MyServlet implements IA,IB{
		// 抽象类和接口都不能创建对象
		public abstract void test();
	}
	
	// 先继承后实现
	class ClassImpl extends MyServlet implements IC{
		@Override
		public void test() {
			System.out.println("test");
		}
	}
	
	@Test
	public void poly() {
		// 多态， 父类引用指向子类对象，引用调用被子类重写的方法，实现多态
		MyServlet ms = new ClassImpl();
		ms.test();
	}
	
	// throw 抛出一个异常对象， throws 声明一个方法有可能出现的异常类型
	public int div(int a,int b) throws Exception{
		if (b == 0) {
			throw new Exception();
		}
		return a / b;
	}
	
	@Test
	public void exception() {
		try {
			div(1,2);
			// 把有可能出问题的代码放到try中尝试运行
		}catch(NullPointerException e) {
			// 一旦抓住就不会抛出给虚拟机
		}catch(Exception e) {
			
		}finally {
			
		}
	}
	
	
	@Test
	public void classes() throws ClassNotFoundException, ParseException {
		// 1.Object类
		Class clazz = Person.class;
		
		Person p = new Person();
		Class<? extends Person> clazz2 = p.getClass();   // 得到当前类类型
		
		Class<?> clazz3 = Class.forName("_1011.review.Review");
		
		// this == obj;
		p.equals(new Person());
		// int的数字
		p.hashCode();
		//  this.getClass().getName()+ "@" + Integer.toHexString(hashCode())
		p.toString();

		// 重写才能使用 clone() 必须要实现Cloneable接口
		// 重写才能使用 finalize() 临终遗言
		
		// 2.String类
		String s1 = "hello";  // 常量池
		String s2 = new String("hello");
		// 字符串类型、8个包装类、文件File类、日期类 已经重写了equals根据字面量比较是否相等
		s1.equals(s2);
		s1.length();
		s1.charAt(0);
		s1.concat("world");
		s1.compareTo("he");
		s1.compareToIgnoreCase("HELLO");
		s1.contains("rl");
		s1.endsWith("ld");
		s1.startsWith("he");
		s1.getBytes();
		s1.toCharArray();
		s1.indexOf("r");
		s1.lastIndexOf("r");
		s1.isEmpty();
		s1.trim();
		s1.substring(0);
//		s1.substring(0, 11);
		String[] split = s1.split("-");
		s1.matches("\\d+");
		s1.replace("l", "L");
		s1.toLowerCase();
		s1.toUpperCase();
		// 静态方法
		String.join("-", "a","b","c","d");
		String.valueOf(true);
		String.format("姓名=%s,年龄=%d,性别=%c,身高=%f,党员:%b","zs",20,'男',1.88,true);
		
		// StringBuilder,StringBuffer
		StringBuffer sb = new StringBuffer();
		sb.append("abc").append(true).append(100);
		sb.insert(0, 1.1);
		sb.setCharAt(0, 'a');
		sb.delete(0, 3);
		sb.deleteCharAt(2);
		sb.reverse();
		String string = sb.toString();
	
		/*
		 * String,StringBuffer,StringBuilder
		 * 1.String不可变字符串，所有的方法都返回新的String
		 * 2.StringBuffer,StringBuilder都带缓存区
		 * 3.StringBuffer线程安全 StringBuilder线程不安全
		 */
		
		// Collection接口 : List接口(有序可重复) + Set接口(无序不可重复)
		//                ArrayList/LinkedList/Vector  HashSet/TreeSet
		List<String> list = new ArrayList<>();
		list.add("abc");
		list.size();
		list.contains("def");
		list.indexOf("abc");
//		list.subList(0, 10);
		list.get(0);
		list.isEmpty();
		list.remove(0);
		list.remove("abc");
		list.sort((a,b)-> a.compareTo(b));
		list.clear();
		
		for(int i = 0 ; i < list.size() ;i ++) {
			System.out.println(list.get(i));
		}
		for(String s : list) {
			System.out.println(s);
		}
		
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		
		ListIterator<String> it2 = list.listIterator();
		while(it2.hasNext()) {
			System.out.println(it2.next());
		}
		while(it2.hasPrevious()) {
			System.out.println(it2.previous());
		}
		
		list.forEach((t) -> System.out.println(t));
		list.forEach(System.out::println);
		
		
		Set<Integer> set = new HashSet<>();
		set.add(100); // Integer.valueOf(100)装箱
		set.size();
		set.contains(100);
		set.isEmpty();
		set.remove(100);
		set.clear();
		
		for(Integer s : set) {
			System.out.println(s);
		}
		
		Iterator<Integer> it3 = set.iterator();
		while(it3.hasNext()) {
			System.out.println(it3.next());
		}
		set.forEach((t) -> System.out.println(t));
		set.forEach(System.out::println);
		
		// Map接口(key-value)： HashMap/Hashtable/ConcurrentHashMap
		Map<Integer,String> map = new HashMap<>();
		map.put(1, "one");
		String value = map.get(1);
		map.containsKey(1);
		map.containsValue("one");
		map.keySet();
		map.values();
		map.remove(1);
		map.clear();
		
		Set<Entry<Integer, String>> entrySet = map.entrySet();
		Iterator<Entry<Integer, String>> it4 = entrySet.iterator();
		while(it4.hasNext()) {
			Entry<Integer, String> entry = it4.next();
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
		
		// Math
		System.out.println(Math.PI);
		System.out.println(Math.abs(-5));   // absolute绝对
		System.out.println(Math.ceil(1.1)); // 天花板
		System.out.println(Math.floor(1.9)); // 地板
		System.out.println(Math.round(1.5)); // 四舍五入
		System.out.println(Math.pow(2, 3));  // 次幂
		System.out.println(Math.sqrt(16));  // 平方根 4
		System.out.println(Math.random());  // 随机数 [0,1)
		
		// 8封装类型
		Integer valueOf = Integer.valueOf("123");
		int parseInt = Integer.parseInt("123");
		Boolean valueOf2 = Boolean.valueOf("false");
		boolean parseBoolean = Boolean.parseBoolean("true");
		System.out.println(Character.isLetter('a'));
		System.out.println(Character.isDigit('1'));
		System.out.println(Character.isWhitespace(' '));
		
		// Random
		Random rand = new Random();
		System.out.println(rand.nextInt()); // int内随机数
		System.out.println(rand.nextInt(100)); // 0~99
		System.out.println(rand.nextBoolean()); // 随机一个boolean
		System.out.println(rand.nextDouble());  // 随机一个double
		System.out.println(rand.ints(4));  // 产生一个int流，有4个元素
		char flower = '♣';
		System.out.println((int)flower);
		
		// Scanner
		Scanner scan = new Scanner(System.in);
		// 看到空格看到回车就断开输入
		//String next = scan.next();
		//System.out.println(next);
		// 回车才断开
//		String nextLine = scan.nextLine();
//		System.out.println(nextLine);
		
		// Arrays
		int[] arr = {12,4,4,54,65};
		Arrays.sort(arr); // 从小到大
		Arrays.binarySearch(arr, 4);  // 二分法查找元素一定是排好序的数组
		
		int[] arr2 = new int[10];
		Arrays.fill(arr2, 100);
		
		System.out.println(Arrays.toString(arr));
		
		// Collections集合工具类
		List<String> list2 = new ArrayList<>();
		Collections.addAll(list2, "abc","def","www");
		Collections.sort(list2); // 集合中的类型就必须要实现Comparable-> compareTo
		Collections.sort(list2, (a,b)-> b.compareTo(a)); // 指定比较的方式，这样集合中的类不需要实现Comparable
		Collections.emptyList(); // []
		Collections.emptySet();  // []
		
		// 日期
		Date d = new Date();
		System.out.println(d);
		SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss.SSS");
		// format日期转字符串
		String format2 = format.format(d);
		System.out.println(format2);
		
		String dateStr = "2023年10月13日 09:28:22.714";
		// parse字符串转日期
		Date parse = format.parse(dateStr);
		System.out.println(parse);
		
		LocalDate d2 = LocalDate.now();
		LocalDate of = LocalDate.of(2026, 1, 2);
		System.out.println(of);
		LocalTime t1 = LocalTime.now();
		LocalTime of2 = LocalTime.of(10, 10,10);
		System.out.println(of2);
		LocalDateTime dt = LocalDateTime.now();
		LocalDateTime dt2 = LocalDateTime.of(2000, 1, 1, 1, 1,1,100);
		System.out.println(dt2);
	}
	
	@Test
	public void io() throws IOException, ClassNotFoundException {
		// File类: 跟文件的创建、删除、改名、移动、属性有关
		File f = new File("a.txt");
		f.exists();
//		f.createNewFile();  // 创建文件
//		f.delete();
//		f.deleteOnExit();  // 退出程序才删除
//		f.mkdir();      //创建目录
		f.isFile();       //判断是否普通文件
		f.isDirectory();     // 判断是否目录
//		File[] listFiles = f.listFiles();  // 得到当前目录下的文件数组
//		String[] list = f.list(); // 得到当前目录下的文件名数组
		
		//文件字节流
		FileInputStream fis = new FileInputStream(f);
		BufferedInputStream bis = new BufferedInputStream(fis);
		byte[] content = new byte[fis.available()];
		bis.read(content);
		bis.close();
		fis.close();
		
		// 第二个参数要是true,追加的写入文件
		FileOutputStream fos = new FileOutputStream(f,true);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		bos.write("hello".getBytes());
		bos.flush();
		bos.close();
		fos.close();
		
		// 文件字符流
		FileReader fr = new FileReader(f);
		BufferedReader br = new BufferedReader(fr);
		char[] content2=  new char[50];
		br.read(content2);
		br.close();
		fr.close();
		
		FileWriter fw = new FileWriter(f,true);
		BufferedWriter bw = new BufferedWriter(fw);
		bw.write("hello world");
		bw.flush();
		bw.close();
		fw.close();
		
		// 必须序列化
		/*
		 * 序列化：把一个对象的属性按顺序写到外部的过程
		 * 反序列化：把一个对象的属性按顺序读回来的过程
		 */
		class Cat implements Serializable{
			int age;
			String name;
			transient char sex;  // 短暂的，不序列化的
			public Cat(int age, String name, char sex) {
				this.age = age;
				this.name = name;
				this.sex = sex;
			}
		}
		
		FileOutputStream fos2 = new FileOutputStream(f);
		ObjectOutputStream oos = new ObjectOutputStream(fos2);
		oos.writeObject(new Cat(1,"mimi",'公'));
		oos.flush();
		oos.close();
		fos2.close();
		
		FileInputStream fis2 = new FileInputStream(f);
		ObjectInputStream ois = new ObjectInputStream(fis2);
		Cat cat  = (Cat) ois.readObject();
		ois.close();
		fis2.close();
	}
	
	
	
	
	interface Myth{
		int add(int a,int b);
	}
	
	@Test
	public void jdk8_lambda() {
		// lambda(接口中只能有唯一的一个抽象方法)是匿名内部类的更新版本
		Myth m2 = (int a,int b) -> {
			return a + b;
		};
		System.out.println(m2.add(11, 220));
		
		Myth m3 = (a,b) -> {
			return a + b;
		};
		System.out.println(m3.add(11, 220));
		
		Myth m4 = (a,b) -> a + b;
		System.out.println(m4.add(11, 220));
		
		//  使用Arrays.asList方式创建的List的长度不可改
		List<String> list = Arrays.asList("123","abc","www","zsaf");
		
		
//		list.forEach(new Consumer<String>(){
//			@Override
//			public void accept(String t) {
//				System.out.println(t);
//			}
//		});
		
		list.forEach(t -> System.out.println(t));
		
//		list.sort(new Comparator<String>() {
//			@Override
//			public int compare(String o1, String o2) {
//				return o1.compareTo(o2);
//			}
//		});
		
		list.sort((o1,o2)->o1.compareTo(o2));
	}
	
	@Test
	public void jdk8_innerFunc() {
		Consumer<String> c = (t) -> System.out.println(t);
		c.accept("hello");
		
		Supplier<Boolean> s = () -> new Random().nextBoolean();
		System.out.println(s.get());
		
		Function<Float,Integer> f = (t) -> Math.round(t);
		System.out.println(f.apply(4.5F));
		
		Predicate<Integer> p = (t) -> t % 2 == 0;
		System.out.println(p.test(10));
	}
	/*
	 * 	// 消费者
	 *  interface Consumer<T>{
	 *     void accept(T t);      // void println(T t);
	 *  }
	 *  interface Supplier<T>{
	 *     T get();               // 对象.length();
	 *  }
	 *  interface Function<T,R>{    
	 *     R apply(T t);     //    double Math.abs(double)
	 *  }
	 *  interface Predicate<T>{
	 *     boolean test(T t)
	 *  }
	 */
	
	interface InterTest{
		String handle(String s,int t);
	}
	
	@Test
	public void jdk8_funcRef() {
		// 静态方法引用    类名::静态方法名;
		/**
		 * interface Function<Double,Double>{
		 *    Double apply(Double a){
		 *    }
		 * }
		 */
		Function<Double,Double> f1 = Math::abs;
		Double apply = f1.apply(-5.5);   // Math.abs(-5.5)
		System.out.println(apply);
		
		// int Integer.parseInt(str);
		Function<String,Integer> f2 = Integer::parseInt;
		Integer apply2 = f2.apply("12345");
		System.out.println(apply2);
		
		Function<int[],String> f3 = Arrays::toString;
		String apply3 = f3.apply(new int[] {1,2,4,5,6,7,8});
		System.out.println(apply3);
		
//		interface Supplier<Integer>{
//		   Integer get();           // int 对象.length();
//		}
		
		// 非静态方法引用  格式： 对象::非静态方法名
		Supplier<Integer> s1 = "hello world"::length;
		Integer integer = s1.get();
		System.out.println(integer);
		
		//boolean "hello".isEmpty()
		Supplier<Boolean> s2 = ""::isEmpty;
		System.out.println(s2.get());
		
		Consumer<String> c = System.out::println;
		c.accept("hello world");  // p.println("hello world")
		
		
		// String substring(int);    缺点：对象是确定的
		Function<Integer,String> f5 = "hello world"::substring;
		String apply4 = f5.apply(5);  // "hello world".substring(5) -> " world"
		System.out.println(apply4);
		
		// 对象不确定，还想用非静态的方法
		// 特殊方法引用   格式：  类名::非静态方法名    (第一个参数是调用方法的对象，第二个参数才是调用方法的第一个参数)
		Predicate<String> p = String::isEmpty;
		boolean test = p.test(""); // "".isEmpty();
		System.out.println(test);
		
		/*
		 * interface InterTest{
				String handle(String s,int t);   
	        //  String substring(      int)
			}
		 */
		InterTest it = String::substring; 
		String handle = it.handle("hello world", 5);
		System.out.println(handle);
		String handle2 = it.handle("hello saflsajf;sajfsa", 10);
		System.out.println(handle2);
	}

	@Test
	public void jdk8_optional() {
		String str = "abc";
		String str2 = null;
		Optional<String> opt = Optional.of(str);
		Optional<String> opt2 = Optional.ofNullable(str2);
		
		// 判断是否有值
		opt.isPresent();
		opt.get();
		opt2.orElse("default");
		// Supplier
		opt2.orElseGet(() -> "default");
	}
	
	@Test
	public void jdk8_stream() {
		List<String> list = new ArrayList<>();
		Collections.addAll(list,"ja1va","he2llo","ad31afda","safsa1234fa","ha32h3a","ab11c","ab33c");
		
		list.stream().count();
		list.stream().distinct();
		list.stream().sorted();  // 从小到大排序
		list.stream().skip(2).limit(4).forEach(System.out::println); 
		list.stream().findFirst().get();
		list.stream().findAny().get();
		System.out.println(list.stream().max((o1,o2)->o1.compareTo(o2)));
		System.out.println(list.stream().min((o1,o2)->o1.compareTo(o2)));
		
		
		// 过滤，遍历流中的每个元素，条件为真添加到新流中
		list.stream().filter((t) -> t.length()>3).forEach(System.out::println); 
		// 映射，遍历流中的每个元素，把元素处理后的值添加到新流中
		list.stream().map((t) -> t.replaceAll("\\d", "")).forEach(System.out::println);
		// reduce
		Optional<String> reduce = list.stream().reduce((t,u) -> t+u);
		System.out.println(reduce.get());
	}
}






